<?php

namespace App\Component\UserIdentity;

use App\Core\Exception\LoginException;
use App\Enums\LoginEnums;
use App\Model\Auth\RoleModel;
use App\Model\Member\MemberModel;
use App\Model\Referrer\ReferrerModel;
use App\Util\ArrayHelper;
use App\Util\CommonHelper;
use EasySwoole\Redis\Redis;
use EasySwoole\Component\Di;
use App\Model\Auth\MenuModel;
use App\Core\IdentityInterface;
use App\Model\Auth\MenuRoleModel;
use App\Core\Exception\DefaultException;
use App\Model\UserModel;
use EasySwoole\RedisPool\RedisPool;

class BackendUser extends \App\Model\UserModel implements IdentityInterface
{
    protected $_jwtExpiredTime;

    /**
     * @param $id
     * @return BackendUser|IdentityInterface|null
     * @throws \EasySwoole\Mysqli\Exception\Exception
     * @throws \EasySwoole\ORM\Exception\Exception
     * @throws \Throwable
     */
    public static function findIdentity($id)
    {
        // TODO: Implement findIdentity() method.
        return static::getOne(['id' => $id]);
    }

    /**
     * @param $username
     * @param $password
     * @return array|bool|\EasySwoole\ORM\AbstractModel|\EasySwoole\ORM\Db\Cursor|\EasySwoole\ORM\Db\CursorInterface
     * @throws DefaultException
     * @throws \EasySwoole\Mysqli\Exception\Exception
     * @throws \EasySwoole\ORM\Exception\Exception
     * @throws \Throwable
     */
    public static function findIdentityByUsername($username, $password)
    {
        $users = static::makeQueryModel(['username' => $username]);
        //系统管理员登录 ss_user
        $role = 'admin';

        $users = $users->all();
        if ($users->isEmpty()) {
            throw new LoginException(LoginEnums::NOT_EXISTS);
        }

        if ($users->count() > 1) {
            throw new DefaultException('该用户名存在相同名字，请使用手机号码登录');
        }

        //第一个用户
        $userModel = $users[0];

        $userModel->role = $role;

        if ($userModel->state == static::DISABLED) {
            throw new LoginException(LoginEnums::DISABLED_ACCOUNT);
        }

        if (empty($userModel->password)) {
            throw new LoginException(LoginEnums::EMPTY_PASSWORD);
        }

        if ($userModel->password <> CommonHelper::pwdEncrypt($password, $userModel->salt)) {
            throw new LoginException(LoginEnums::ERROR_PASSWORD);
        }

        return $userModel;
    }

    public function getId()
    {
        // TODO: Implement getId() method.
        return $this->id;
    }

    public function getUserId()
    {
        // TODO: Implement getId() method.
        return $this->id;
    }

    /**
     * 读取jwt-token过期时间
     * @return mixed
     */
    public function getJwtExpiredTime(): int
    {
        if ($this->_jwtExpiredTime === null) {
            $this->setJwtExpiredTime(time() + 3600);
        }
        return $this->_jwtExpiredTime;
    }

    /**
     * 设置jwt-token过期时间
     * @param $expiredTime
     * @return $this
     */
    public function setJwtExpiredTime($expiredTime)
    {
        $this->_jwtExpiredTime = $expiredTime;
        return $this;
    }

    public function getJwtData(): array
    {
        // TODO: Implement getJwtData() method.
        return ['id' => $this->getId(), 'username' => $this->getUsername(), 'type' => $this->getType()];
    }

    /**
     * 获取账户名
     * @return string
     */
    public function getUsername(): string
    {
        return $this->username;
    }

    public function afterLogin()
    {
        // TODO: Implement afterLogin() method.
        $this->setAuth();
    }

    /**
     * 获取用户名
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * 获取当前用户角色id
     * @return int
     */
    public function getRoleId()
    {
        return $this->role_id;
    }

    /**
     * 获取当前用户角色id
     * @return int
     */
    public function getType(): int
    {
        return $this->type;
    }

    public function getSalt()
    {
        return $this->salt;
    }
    public function getPassword()
    {
        return $this->password;
    }
    /**
     * 设置权限数组
     * @param $auth_list
     * @return bool
     */
    public function setAuth()
    {
        //缓存key
        $cache_key = "userInfoAuth:" . $this->getId();

        //实例化
        /** @var Redis $cache */
//        $cache = Di::getInstance()->get("REDIS");
        $cache = RedisPool::defer();
        if ($cache->exists($cache_key)) {
            return true;
        }

        //获取权限
        $auth_list = $this->getAuthList();
        //保存数据
        $cache->set($cache_key, serialize($auth_list), 60 * 60);

        return true;
    }

    /**
     * 设置权限数组
     * @param $auth
     * @return bool
     */
    public function checkAuth($auth)
    {
        //缓存key
        $cache_key = "userInfoAuth:" . $this->getId();

        //实例化
//        $cache = Di::getInstance()->get("REDIS");
        $cache = RedisPool::defer();
        //获取数据
        /** @var Redis $cache */
        $auth_list = $cache->get($cache_key);

        $auth_list = unserialize($auth_list);

        //查询是否存在
        if (!in_array($auth, $auth_list)) {
            return false;
        }

        //缓存续期
        $cache->set($cache_key, serialize($auth_list), 60 * 60);

        return true;
    }

    public function getAuthList()
    {
        if (!$this->auth_list) {
            $this->getMenuRole();
        }
        return $this->auth_list;
    }

    /**
     * 获取角色web菜单
     * @return mixed|null
     * @throws \EasySwoole\ORM\Exception\Exception
     * @throws \Throwable
     */
    public function getMenuTree()
    {
        if (!$this->menu_tree) {
            $this->getMenuRole();
        }
        return $this->menu_tree;
    }

    /**
     * 获取当前用户菜单
     * @throws \EasySwoole\ORM\Exception\Exception
     * @throws \Throwable
     */
    public function getMenuRole()
    {
        $role_id = $this->getRoleId();
        $menu_model = new MenuModel();
        $list = $menu_model->getLists();

        //非超管，需要过滤菜单
        if ($role_id <> RoleModel::TYPE_INSIDE) {
            foreach ($list as $key => $item) {
                if ($item['menu_type'] == MenuModel::MENU_TYPE_INSIDE) {
//                    unset($list[$key]);
                }
            }
        }

        //查询路由权限
        $menu_ids = MenuRoleModel::makeQueryModel(['role_id' => $role_id])->column('menu_id');

        $pk = 'id';

        $pid = 'pid';

        $tree = [];

        $auth_list = [];

        //路由接口为空，则无权限
        if (empty($menu_ids)) {
            return [$auth_list, $tree];
        }

        if (is_array($list)) {
            // 创建基于主键的数组引用
            $refer = [];

            foreach ($list as $key => $data) {
                //判断是否存在权限 顶menu_id为0，则表示全局有权限
                if (!(current($menu_ids) == 0 || in_array($data['id'], $menu_ids))) {
                    unset($list[$key]);
                    continue;
                }

                $refer[$data[$pk]] = &$list[$key];

                //过滤以view_开始的，改模块为前端控制页面
                if (!empty($data['identification']) && !(strpos($data['identification'], 'view_') === 0)) {
                    $temp = explode(',', strtolower($data['identification']));
                    $auth_list = ArrayHelper::merge($auth_list, $temp);
                }
            }

            //过滤重复权限
            $auth_list = array_unique($auth_list);
            $auth_list = array_values($auth_list);

            foreach ($list as $key => $data) {
                // 判断是否存在parent
                $parentId = $data[$pid];
                $level = CommonHelper::findParentLevel($refer, $parentId, $pid);

                $list[$key]['__lvl'] = $level;
                if (empty($parentId)) {
                    $tree[] = &$list[$key];
                } else {
                    if (isset($refer[$parentId])) {
                        $parent = &$refer[$parentId];
                        if ($list[$key]['type'] == MenuModel::TYPE_VIEW) {
                            $parent['child'][] = &$list[$key];
                        }
                    }
                }
            }
        }

        $this->auth_list = $auth_list;

        $this->menu_tree = $tree;
    }


    /**
     * @param array $jwtData
     * @return BackendUser|IdentityInterface|null
     * @throws \EasySwoole\Mysqli\Exception\Exception
     * @throws \EasySwoole\ORM\Exception\Exception
     * @throws \Throwable
     */
    public static function parseJwtData(array $jwtData)
    {
        $id = $jwtData['id'];
        $type = $jwtData['type'];
        if($type == self::TYPE_INSIDE) {
            $identity = self::findIdentity($id);
        }else{

        }
        $identity->setJwtExpiredTime($jwtData['jwt_exp']);

        return $identity;
    }
}
